<template>
  <div id="container"></div>
</template>

<script setup>
import {ref, onMounted, toRaw} from 'vue'
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import Stats from "three/addons/libs/stats.module.js"; //gltf

const container = ref(null); //界面需要渲染的容器
const scene = ref(null);	// 场景对象
const camera =  ref(null); //相机对象
const renderer = ref(null); //渲染器对象
const controller =  ref(null);	// 相机控件对象
const clock = ref(new THREE.Clock());// 创建一个clock对象，用于跟踪时间
const orbit = ref(null);//labelRenderer控制器
const stats = ref(null);//labelRenderer控制器

onMounted(() => {
  init()
  animate()  //如果引入了模型并存在动画，可在模型引入成功后加载动画
  window.addEventListener("resize", onWindowSize)
})

/**
 * @description 初始化
 */
function init() {
  container.value = document.getElementById('container')
  setScene()
  setCamera()
  setRenderer()
  setController()
  addHelper()
  setLight()
  addStatus()
}
/**
 * @description 创建场景
 */
function setScene() {
  // 创建场景对象Scene
  scene.value = new THREE.Scene()
  // 设置场景背景
  // scene.value.background = new THREE.Color(0xbfe3dd);
}
/**
 * @description 创建相机
 */
function setCamera() {
  // 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
  camera.value = new THREE.PerspectiveCamera(45, container.value.clientWidth / container.value.clientHeight, 0.1, 1000)
  // 设置相机位置
  camera.value.position.set(80, 80, 80)
  // 设置摄像头宽高比例
  camera.value.aspect = container.value.clientWidth / container.value.clientHeight;
  // 设置摄像头投影矩阵
  camera.value.updateProjectionMatrix();
  // 设置相机视线方向
  camera.value.lookAt(new THREE.Vector3(0, 0, 0))// 0, 0, 0 scene.value.position
  // 将相机加入场景
  scene.value.add(camera.value)
}
/**
 * @description 创建渲染器
 */
function setRenderer() {
  // 初始化渲染器
  renderer.value = new THREE.WebGLRenderer({
    antialias: true,// 设置抗锯齿
    alpha: false,
    logarithmicDepthBuffer: true,  // 是否使用对数深度缓存
  })
  // 设置渲染器宽高
  renderer.value.setSize(container.value.clientWidth, container.value.clientHeight);
  // 设置渲染器的像素比
  renderer.value.setPixelRatio(window.devicePixelRatio);
  // 是否需要对对象排序
  // renderer.value.sortObjects = false;
  // 将渲染器添加到页面
  container.value.appendChild(renderer.value.domElement);

}
/**
 * @description 添加创建控制器
 */
function setController() {
  controller.value = new OrbitControls(camera.value, renderer.value.domElement);
  // 控制缩放范围
  // controller.value.minDistance = 1;
  // controller.value.maxDistance = 5;
  //是否开启右键拖拽
  controller.value.enablePan = false;
  // 阻尼（惯性）
  controller.value.enableDamping = true; //启用阻尼（惯性）
  controller.value.dampingFactor = 0.04; //阻尼惯性有多大
  // controller.value.autoRotate = true; //自动围绕目标旋转
  // controller.value.minAzimuthAngle = -Math.PI / 3; //能够水平旋转的角度下限。如果设置，其有效值范围为[-2 * Math.PI，2 * Math.PI]，且旋转角度的上限和下限差值小于2 * Math.PI。默认值为无穷大。
  // controller.value.maxAzimuthAngle = Math.PI / 3;//水平旋转的角度上限,其有效值范围为[-2 * Math.PI，2 * Math.PI],默认值为无穷大
  // controller.value.minPolarAngle = 1; //能够垂直旋转的角度的下限，范围是0到Math.PI，其默认值为0。
  // controller.value.maxPolarAngle = Math.PI - 0.1; //能够垂直旋转的角度的上限，范围是0到Math.PI，其默认值为Math.PI。
  // 修改相机的lookAt是不会影响THREE.OrbitControls的target的
  // 由于设置了控制器，因此只能改变控制器的target以改变相机的lookAt方向
  controller.value.target.set(0, 0.5, 0); //控制器的焦点

}
/**
 * @description 创建辅助坐标轴
 */
function addHelper() {
  // 模拟相机视锥体的辅助对象
  let helper = new THREE.CameraHelper(camera.value);
  // scene.value.add(helper);
  //创建辅助坐标轴、轴辅助 （每一个轴的长度）
  let axisHelper = new THREE.AxesHelper(150);  // 红线是X轴，绿线是Y轴，蓝线是Z轴
  scene.value.add(axisHelper)
  // 坐标格辅助对象
  let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
  // scene.value.add(gridHelper);
}
/**
 * @description 设置光源
 */
function setLight() {
  // 环境光
  scene.value.add(new THREE.AmbientLight(0x7af4ff, 1.5));
  // 平行光
  let directionalLight1 = new THREE.DirectionalLight(0x7af4ff, 1);
  directionalLight1.position.set(-100, 10, -100);
  scene.value.add(directionalLight1);
  // 平行光
  let directionalLight2 = new THREE.DirectionalLight(0x7af4ff, 1);
  directionalLight2.position.set(100, 10, 100);
  scene.value.add(directionalLight2);
}
/**
 * @description 创建性能监听器
 */
function addStatus() {
  // 创建一个性能监听器
  stats.value = new Stats();
  // 将性能监听器添加到容器中
  container.value.appendChild(stats.value.dom);
}


/**
 * @description 监听屏幕的大小改变，修改渲染器的宽高，相机的比例
 */
// 窗口变化
function onWindowSize() {
  orbit.value && orbit.value.update();
  // 更新摄像头
  camera.value.aspect = container.value.clientWidth / container.value.clientHeight;
  // 更新摄像机的投影矩阵
  camera.value.updateProjectionMatrix();
  //更新渲染器
  renderer.value.setSize(container.value.clientWidth, container.value.clientHeight);
  // 设置渲染器的像素比
  renderer.value.setPixelRatio(window.devicePixelRatio)
}
/**
 * @description 动画执行函数
 */
function animate() {
  const delta = clock.value.getDelta();
  // 引擎自动更新渲染器
  requestAnimationFrame(animate);
  //update()函数内会执行camera.lookAt(x, y, z)
  controller.value.update(delta);
  // 更新性能监听器
  stats.value.update();
  // 重新渲染场景
  renderer.value.render(toRaw(scene.value), camera.value);
}

</script>

<style>
#container {
  position: absolute;
  width: 100%;
  height: 100%;
}
</style>
